﻿#region MIT Licenze
//The MIT License

//Copyright (c) 2008 Sebastian Faltoni, dotnetfireball.org

//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Fireball.OpenXML;
using Fireball.Extensions;

namespace Fireball.OpenXML.Word
{
    /// <summary>
    /// This class rappresent a Word Style, a style
    /// is a set of properties that can be applied to one
    /// or more OpenXML Entity
    /// </summary>
    public class Style : OpenXMLEntity
    {

        //public static readonly XNamespace XStyle = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
        //public static readonly XNamespace RelationsShip = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";


        public bool? IsDefault
        {
            get;
            set;
        }


        public bool? IsCustomStyle
        {
            get;
            set;
        }

        public bool? IsPrimaryStyle { get; set; }

        public string StyleID
        {
            get;
            set;
        }

        public string Aliases
        {
            get;
            set;
        }

        public string BasedOn
        {
            get;
            set;
        }

        public string Type { get; set; }

        public bool? AutoRedefine
        {
            get;
            set;
        }

        public bool? Hidden
        {
            get;
            set;
        }

        public bool? SemiHidden
        {
            get;
            set;
        }

        public bool? UnHideWhenUsed
        {
            get;
            set;
        }

        public bool? Locked
        {
            get;
            set;
        }

        public bool? Personal
        {
            get;
            set;
        }

        public bool? PersonalCompose
        {
            get;
            set;
        }

        public bool? PersonalReply
        {
            get;
            set;
        }

        public long? RevisionID
        {
            get;
            set;
        }

        public StyleParagraphProperties ParagraphProperties
        {
            get;
            set;
        }

        public StyleRunProperties RunProperties
        {
            get;
            set;
        }


        /// <summary>
        /// Default properties for tables
        /// </summary>
        public StyleTableProperties TableProperties
        {
            get;
            set;
        }

        /// <summary>
        /// The ui Priority
        /// </summary>
        public int? UIPriority
        {
            get;
            set;
        }

        private void ParseInternal(XElement xStyle)
        {
            var aliases = xStyle.Element(NS.WM + "aliases");

            this.StyleID = xStyle.Attribute(NS.WM + "styleId").Value;

            var name = xStyle.Element(NS.WM + "name");

            if (name != null)
            {
                this.Name = name.GetOfficeValAttribute();
            }

            var uiPriority = xStyle.Element(NS.WM + "uiPriority");

            if (uiPriority != null)
            {
                this.UIPriority = Convert.ToInt32(uiPriority.GetOfficeValAttribute());
            }

            var semiHidden = xStyle.Element(NS.WM + "semiHidden");

            if (semiHidden != null)
            {
                this.SemiHidden = true;
            }
            else
                this.SemiHidden = null;

            var unHideWhenUsed = xStyle.Element(NS.WM + "UnHideWhenUsed");

            if (unHideWhenUsed != null)
            {
                this.UnHideWhenUsed = true;
            }
            else
                this.UnHideWhenUsed = null;


            if (aliases != null)
            {
                this.Aliases = aliases.GetOfficeValAttribute();
            }

            var basedOn =  xStyle.Element(NS.WM + "basedOn");

            if (basedOn != null)
            {
                this.BasedOn = basedOn.GetOfficeValAttribute();
            }

            var autoRedefine = xStyle.Element(NS.WM + "autoRedefine");

            if (autoRedefine != null)
            {
                this.AutoRedefine = autoRedefine.GetOfficeValAttribute().ToBoolean();
            }

            var hidden = xStyle.Element(NS.WM + "hidden");

            if (hidden != null)
            {
                this.Hidden = hidden.GetOfficeValAttribute().ToBoolean();
            }

            var qFormat = xStyle.Element(NS.WM + "qFormat");

            if (qFormat != null)
                this.IsPrimaryStyle = true;
            else
                this.IsPrimaryStyle = null;

            var tblPr = xStyle.Element(NS.WM + "tblPr");

            if (tblPr != null)
            {
                this.TableProperties = StyleTableProperties.Parse(tblPr);
            }

            var locked = xStyle.Element(NS.WM + "locked");

            if (locked != null)
                this.Locked = true;
            else
                this.Locked = null;

            var personal = xStyle.Element(NS.WM + "personal");

            if (personal != null)
            {
                this.Personal = true;
            }
            else
                this.Personal = null;

            var personalCompose = xStyle.Element(NS.WM + "personalCompose");

            if (personalCompose != null)
                this.PersonalCompose = true;
            else
                this.PersonalCompose = null;

            var personalReply = xStyle.Element(NS.WM + "personalReply");

            if (personalReply != null)
                this.PersonalReply = true;
            else
                this.PersonalReply = null;

            var pPr = xStyle.Element(NS.WM + "pPr");

            var revisionId = xStyle.Element(NS.WM + "rsid");

            if (revisionId != null)
            {
                this.RevisionID = long.Parse(revisionId.Attribute(NS.WM + "val").Value, System.Globalization.NumberStyles.HexNumber);
            }

            if (pPr != null)
            {
                this.ParagraphProperties = StyleParagraphProperties.Parse(pPr);
            }

            var rPr = xStyle.Element(NS.WM + "rPr");

            if (rPr != null)
            {
                this.RunProperties = StyleRunProperties.Parse(rPr);
            }

        }


        public static Style Parse(XElement xStyle)
        {
            if (xStyle.Name.LocalName != "style")
            {
                throw new Exception("Invalid XElement");
            }
            var style = new Style();

            style.ParseInternal(xStyle);

            return style;
        }

        public override XContainer ToXml()
        {
            XElement xStyle = new XElement(NS.WM + "style");

            if (!string.IsNullOrEmpty(this.Type))
            {
                xStyle.Add(new XAttribute(NS.WM + "type", this.Type));
            }

            if (this.IsDefault != null)
                xStyle.Add(new XAttribute(NS.WM + "default", this.IsDefault.Value.ToOnOff()));

            if (!string.IsNullOrEmpty(this.StyleID))
                xStyle.Add(new XAttribute(NS.WM + "styleId", this.StyleID));

            if(!string.IsNullOrEmpty(this.Name))
            {
                xStyle.Add(new XElement(NS.WM + "name",
                    new XAttribute(NS.WM + "val", this.Name)));
            }

            if (this.UIPriority != null)
            {
                xStyle.Add(new XElement(NS.WM + "uiPriority",
                    new XAttribute(NS.WM + "val", this.UIPriority.Value)));
            }

            if (this.SemiHidden != null)
            {
                if (this.SemiHidden.Value == true)
                {
                    xStyle.Add(new XElement(NS.WM + "semiHidden"));
                }
            }

            if (this.UnHideWhenUsed != null)
            {
                if (this.UnHideWhenUsed.Value == true)
                {
                    xStyle.Add(new XElement(NS.WM + "unhideWhenUsed"));
                }
            }

            if (!string.IsNullOrEmpty(this.Aliases))
            {
                xStyle.Add(new XElement(NS.WM + "aliases",
                    new XAttribute(NS.WM + "val", this.Aliases)));
            }

            if (!string.IsNullOrEmpty(this.BasedOn))
            {
                xStyle.Add(new XElement(NS.WM + "basedOn",
                    new XAttribute(NS.WM + "val", this.BasedOn)));
            }

            if (this.AutoRedefine != null)
            {
                xStyle.Add(new XElement(NS.WM + "autoRedefine",
                    new XAttribute(NS.WM + "val", this.AutoRedefine.Value.ToOnOff())));
            }

            if (this.Hidden != null)
            {
                xStyle.Add(new XElement(NS.WM + "hidden",
                    new XAttribute(NS.WM + "val", this.Hidden.Value.ToOnOff())));
            }

            if (this.IsPrimaryStyle != null)
                if (this.IsPrimaryStyle.Value)
                    xStyle.Add(new XElement(NS.WM + "qFormat"));

            if (this.TableProperties != null)
            {
                xStyle.Add(this.TableProperties.ToXml());
            }

            if (this.Locked != null)
            {
                xStyle.Add(new XElement(NS.WM + "locked",
                    new XAttribute(NS.WM + "val", this.Locked.Value.ToOnOff())));
            }

            if (this.Personal != null)
            {
                xStyle.Add(new XElement(NS.WM + "personal",
                    new XAttribute(NS.WM + "val", this.Personal.Value.ToOnOff())));
            }

            if (this.PersonalCompose != null)
            {
                xStyle.Add(new XElement(NS.WM + "personalCompose",
                    new XAttribute(NS.WM + "val", this.PersonalCompose.Value.ToOnOff())));
            }

            if (this.PersonalReply != null)
            {
                xStyle.Add(new XElement(NS.WM + "personalReply",
                    new XAttribute(NS.WM + "val", this.PersonalReply.Value.ToOnOff())));
            }

            if (this.RevisionID != null)
            {
                xStyle.Add(new XElement(NS.WM + "rsid",
                    new XAttribute(NS.WM + "val", this.RevisionID.Value.ToHex8())));
            }

            if (this.ParagraphProperties != null)
                xStyle.Add(this.ParagraphProperties.ToXml());

            if (this.RunProperties != null)
                xStyle.Add(this.RunProperties.ToXml());

            return xStyle;
        }
    }
}
